﻿using System;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Razor.Generator;
using System.Web.Routing;
using HtmlAgilityPack;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace Library.MVCHelpers
{
    public static class ViewHelper
    {
        #region Rebuilt HTML Content

        public static string RebuildHTMLContent(string htmlContent)
        {
            if (string.IsNullOrWhiteSpace(htmlContent))
                return htmlContent;

            var htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(htmlContent);

            // Rebuil images
            var images = htmlDoc.DocumentNode.SelectNodes("//img");
            if (images != null)
            {
                foreach (var image in images)
                {
                    // Replace src to data-src for lazy loading
                    //image.SetAttributeValue("data-src", image.Attributes["src"].Value);
                    //image.Attributes["src"].Remove();

                    // Replace CSS class
                    if (image.Attributes["class"] == null || string.IsNullOrWhiteSpace(image.Attributes["class"].Value))
                    {
                        image.SetAttributeValue("class", "img-responsive lazy");
                    }
                    else
                    {
                        image.SetAttributeValue("class", "img-responsive lazy " + image.Attributes["class"].Value);
                    }

                    if (image.Attributes["alt"] != null && !string.IsNullOrWhiteSpace(image.Attributes["alt"].Value))
                    {
                        var figure = htmlDoc.CreateElement("figure");
                        figure.SetAttributeValue("class", "img-container");

                        var figcaption = htmlDoc.CreateElement("figcaption");
                        var newImg = htmlDoc.CreateElement("img");
                        newImg.SetAttributeValue("data-src", image.Attributes["src"].Value);

                        var hasFloat = false;
                        if (image.Attributes["class"].Value.Contains("pull-left"))
                        {
                            newImg.SetAttributeValue("class", image.Attributes["class"].Value.Replace("pull-left", string.Empty).Trim());
                            figure.SetAttributeValue("class", "img-container pull-left");
                            hasFloat = true;
                        }
                        else if (image.Attributes["class"].Value.Contains("pull-right"))
                        {
                            newImg.SetAttributeValue("class", image.Attributes["class"].Value.Replace("pull-right", string.Empty).Trim());
                            figure.SetAttributeValue("class", "img-container pull-right");
                            hasFloat = true;
                        }
                        //else if (image.Attributes["class"].Value.Contains("center-block"))
                        //{
                        //    newImg.SetAttributeValue("class", image.Attributes["class"].Value);
                        //    figcaption.SetAttributeValue("class", "center-block");
                        //}
                        else
                        {
                            newImg.SetAttributeValue("class", image.Attributes["class"].Value);
                        }
                        newImg.SetAttributeValue("class", newImg.Attributes["class"].Value + " center-block");
                        newImg.SetAttributeValue("alt", image.Attributes["alt"].Value);
                        if (image.Attributes["style"] != null && !string.IsNullOrWhiteSpace(image.Attributes["style"].Value))
                        {
                            //newImg.SetAttributeValue("style", image.Attributes["style"].Value);

                            var styles = image.Attributes["style"].Value.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                            var newStyles = new StringBuilder();
                            foreach (var style in styles)
                            {
                                if (!style.Trim().StartsWith("width") && !style.Trim().StartsWith("height") && !style.Trim().StartsWith("float"))
                                {
                                    newStyles.Append(style.Trim() + ";");
                                }

                                if (style.Trim().StartsWith("float"))
                                {
                                    var a = style.Trim().Split(':');
                                    if (a.Length > 1)
                                    {
                                        var floatValue = "pull-" + a[1].Trim();
                                        if (!figure.Attributes["class"].Value.Contains(floatValue))
                                        {
                                            figure.SetAttributeValue("class", figure.Attributes["class"].Value + " " + floatValue);
                                            hasFloat = true;
                                        }
                                    }
                                }
                            }

                            newImg.SetAttributeValue("style", newStyles.ToString());
                        }

                        if (figcaption.Attributes["class"] != null && !string.IsNullOrWhiteSpace(figcaption.Attributes["class"].Value))
                        {
                            figcaption.SetAttributeValue("class", "img-caption " + figcaption.Attributes["class"].Value.Trim());
                        }
                        else
                        {
                            figcaption.SetAttributeValue("class", "img-caption");
                        }

                        figcaption.InnerHtml = image.Attributes["alt"].Value;

                        figure.AppendChild(newImg);
                        figure.AppendChild(figcaption);
                        if (hasFloat)
                            figure.AppendChild(CreateClearFix(htmlDoc));

                        if (image.ParentNode != null)
                        {
                            if (image.ParentNode.Name == "p" && image.ParentNode.Attributes["class"] != null && image.ParentNode.Attributes["class"].Value.Contains("text-center"))
                            {
                                var div = htmlDoc.CreateElement("div");
                                div.SetAttributeValue("class", "text-center");
                                div.AppendChild(figure);
                                image.ParentNode.ReplaceChild(div, image);
                            }
                            else
                            {
                                image.ParentNode.ReplaceChild(figure, image);
                            }
                        }
                        else
                        {
                            htmlDoc.DocumentNode.ReplaceChild(figure, image);
                        }
                    }
                }
            }

            return htmlDoc.DocumentNode.OuterHtml;
        }

        public static HtmlNode CreateClearFix(HtmlDocument htmlDoc)
        {
            if (htmlDoc == null)
                return null;

            var clearfix = htmlDoc.CreateElement("div");
            clearfix.SetAttributeValue("class", "clearfix");
            return clearfix;
        }

        public static string ReplaceAtSignCodes(string content, BaseController controller)
        {
            if (string.IsNullOrWhiteSpace(content))
                return content;

            content = content.Replace("@@ContactForm@@", string.Format("<div id=\"contactformctnr\">{0}</div>", controller.RenderPartialViewToString("Contact")));

            return content;
        }

        #endregion
        public static T CreateController<T>(RouteData routeData = null) where T : Controller, new()
        {
            // create a disconnected controller instance
            T controller = new T();

            // get context wrapper from HttpContext if available
            HttpContextBase wrapper;
            if (HttpContext.Current != null)
                wrapper = new HttpContextWrapper(HttpContext.Current);
            else
                throw new InvalidOperationException("Can't create Controller Context if no active HttpContext instance is available.");

            if (routeData == null)
                routeData = new RouteData();

            // add the controller routing if not existing
            if (!routeData.Values.ContainsKey("controller") && !routeData.Values.ContainsKey("Controller"))
                routeData.Values.Add("controller", controller.GetType().Name.ToLower().Replace("controller", ""));

            controller.ControllerContext = new ControllerContext(wrapper, routeData, controller);
            return controller;
        }

        #region Classes

        public class HttpStatusCodeJsonResult : JsonResult
        {
            public HttpStatusCodeJsonResult(HttpStatusCode statusCode)
            {
                Data = new
                {
                    @status = statusCode
                };
            }

            public HttpStatusCodeJsonResult(HttpStatusCode statusCode, string statusDescription)
            {
                ContentEncoding = Encoding.UTF8;
                Data = new
                {
                    @status = statusCode,
                    @message = statusDescription
                };
            }

            public HttpStatusCodeJsonResult(HttpStatusCode statusCode, int modelId, string responseHtml)
            {
                ContentEncoding = Encoding.UTF8;
                Data = new
                {
                    @status = statusCode,
                    @id = modelId,
                    @html = responseHtml
                };
            }

            public HttpStatusCodeJsonResult(HttpStatusCode statusCode, string relativeValue, string responseHtml)
            {
                ContentEncoding = Encoding.UTF8;
                Data = new
                {
                    @status = statusCode,
                    @relative = relativeValue,
                    @html = responseHtml
                };
            }

            public HttpStatusCodeJsonResult(HttpStatusCode statusCode, int modelId, int refId, string responseHtml)
            {
                ContentEncoding = Encoding.UTF8;
                Data = new
                {
                    @status = statusCode,
                    @id = modelId,
                    @refid = refId,
                    @html = responseHtml
                };
            }

            public HttpStatusCodeJsonResult(HttpStatusCode statusCode, int modelId)
            {
                Data = new
                {
                    @status = statusCode,
                    @id = modelId
                };
            }

            public HttpStatusCodeJsonResult(HttpStatusCode statusCode, object responseObject)
            {
                Data = new
                {
                    @status = statusCode,
                    @object = JsonConvert.SerializeObject(responseObject)
                };
            }
        }

        public class NOWJsonSerializerSettings : JsonSerializerSettings
        {
            public NOWJsonSerializerSettings()
                : base()
            {
                ContractResolver = new LowercaseContractResolver();
            }
        }

        public class LowercaseContractResolver : DefaultContractResolver
        {
            protected override string ResolvePropertyName(string propertyName)
            {
                return propertyName.ToLower();
            }
        }

        #endregion
    }
}
